/*
 * Copyright 2011-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0.
 * See `LICENSE` in the project root for license information.
 */

package me.ijleex.mgmt.framework.validation;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.hibernate.validator.HibernateValidator;

import me.ijleex.mgmt.framework.entity.Result;

/**
 * Hibernate-Validator 校验参数
 *
 * @author liym
 * @since 2019-08-27 22:21 新建
 */
public final class FastValidator {

    /**
     * 校验工厂（快速失败返回模式）
     *
     * <p><a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-provider-specific-settings">x</a></p>
     */
    private static final ValidatorFactory VALIDATOR_FACTORY = Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)
            .buildValidatorFactory();
    /**
     * 校验工具
     */
    private static final Validator VALIDATOR = VALIDATOR_FACTORY.getValidator();

    private FastValidator() {}

    /**
     * 快速校验对象
     * <p><b>只要有一个验证失败，则直接返回</b></p>
     *
     * @param <T> 参数类型
     * @param object 参数对象
     * @param groups 分组
     * @return 校验结果 {@link Result}
     * @since 2019-08-27 22:23
     */
    public static <T> Result validate(T object, Class<?>... groups) {
        Set<ConstraintViolation<T>> violationSet = VALIDATOR.validate(object, groups);
        if (violationSet.isEmpty()) {
            return Result.ok();
        } else {
            ConstraintViolation<T> violation = violationSet.iterator().next();
            String message = violation.getMessage();
            return Result.invalidArg(message);
        }
    }

    /**
     * 快速校验对象的某个属性
     *
     * @param <T> 参数类型
     * @param object 参数对象
     * @param propertyName 属性名称
     * @return 校验结果 {@link Result}
     * @since 2019-08-27 22:50
     */
    public static <T> Result validateProperty(T object, String propertyName) {
        Set<ConstraintViolation<T>> violationSet = VALIDATOR.validateProperty(object, propertyName);
        if (violationSet.isEmpty()) {
            return Result.ok();
        } else {
            ConstraintViolation<T> violation = violationSet.iterator().next();
            String message = violation.getMessage();
            return Result.invalidArg(message);
        }
    }

}
